package com.winexpress.util;

import com.google.gdata.client.analytics.AnalyticsService;
import com.google.gdata.client.analytics.DataQuery;
import com.google.gdata.data.analytics.DataEntry;
import com.google.gdata.data.analytics.DataFeed;

import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class GoogleAnalytics {

    private static final String CLIENT_USERNAME = "winexpresssupergroup@gmail.com";
    private static final String CLIENT_PASS = "adminwine";
    private static final String TABLE_ID = "ga:84747036";

    private static String totalPageViews;
    private static String totalVisits;
    private static String totalNewVisits;
    private String uniqueVisitors;
    private static String avgVisitDuration;
    private static String avgVisitDuration_hour;
    private static String avgVisitDuration_min;
    private static String avgVisitDuration_sec;
    private static String bounceRate;
    private static String percentNewVisits;
    private static String pagesPerVisit;

    private static List<String> days;
    private static List<String> pageViewsByDay;
    private static List<String> visitsByDay;
    private static List<String> newVisitsByDay;

    public void runGoogleAnalytics() {
        try {
            // Service Object to work with the Google Analytics Data Export API.
            AnalyticsService analyticsService = new AnalyticsService("gaExportAPI_acctSample_v2.1");

            // Client Login Authorization.
            analyticsService.setUserCredentials(CLIENT_USERNAME, CLIENT_PASS);

            // Access the Data Feed if the Table Id has been set.
            if (!TABLE_ID.isEmpty()) {
                // Get profile data from the Data Feed.
                getDataFeed(analyticsService);
            }

        } catch (AuthenticationException e) {
            System.err.println("Authentication failed : " + e.getMessage());
            return;
        } catch (IOException e) {
            System.err.println("Network error trying to retrieve feed: "
                    + e.getMessage());
            return;
        } catch (ServiceException e) {
            System.err.println("Analytics API responded with an error message: "
                    + e.getMessage());
            return;
        }
    }

    private void getDataFeed(AnalyticsService analyticsService)
            throws IOException, MalformedURLException, ServiceException {

        // Create a query using the DataQuery Object.
        DataQuery query = new DataQuery(new URL("https://www.google.com/analytics/feeds/data"));

        Calendar originalDate = Calendar.getInstance();
        String endDate = new SimpleDateFormat("yyyy-MM-dd").format(originalDate.getTime());
        Calendar previousWeekDay = (Calendar) originalDate.clone();
        previousWeekDay.add(Calendar.WEEK_OF_YEAR, -1);
        String startDate = new SimpleDateFormat("yyyy-MM-dd").format(previousWeekDay.getTime());
        //query.setStartDate("2014-03-01");
        query.setStartDate(startDate);
        query.setEndDate(endDate);

        //query.setDimensions("ga:pageTitle,ga:pagePath");
        query.setDimensions("ga:pageTitle");
        query.setMetrics("ga:pageviews,ga:bounces,ga:visits,ga:newVisits,ga:visitors,ga:avgTimeOnSite,ga:visitBounceRate,ga:percentNewVisits,ga:pageviewsPerVisit");
        //query.setSort("-ga:pageviews");
        query.setMaxResults(10);
        query.setIds(TABLE_ID);

        // Make a request to the API.
        DataFeed dataFeed = analyticsService.getFeed(query.getUrl(),
                DataFeed.class);

        // Output data to the screen.
        System.out.println("----------- Data Feed Results ----------");
        for (DataEntry entry : dataFeed.getEntries()) {
            System.out.println("\nPage Title = "
                    + entry.stringValueOf("ga:pageTitle") + "\nPage Path  = "
                    + entry.stringValueOf("ga:pagePath") + "\nPageviews  = "
                    + entry.stringValueOf("ga:pageviews") + "\nga:bounces = " //page view
                    + entry.stringValueOf("ga:bounces") + "\nga:visits = "
                    + entry.stringValueOf("ga:visits") + "\nga:New Visits = " //visits
                    + entry.stringValueOf("ga:newVisits") + "\nga:visitors = " //new visits     
                    + entry.stringValueOf("ga:visitors"));

            totalPageViews = entry.stringValueOf("ga:pageviews").toString();
            totalVisits = entry.stringValueOf("ga:visits").toString();
            totalNewVisits = entry.stringValueOf("ga:newVisits").toString();
            uniqueVisitors = entry.stringValueOf("ga:visitors").toString();
            avgVisitDuration = this.roundDecimal(entry.stringValueOf("ga:avgTimeOnSite").toString());
            this.setAvgTimeOnSite(avgVisitDuration);
            bounceRate = this.roundDecimal(entry.stringValueOf("ga:visitBounceRate").toString());
            percentNewVisits = this.roundDecimal(entry.stringValueOf("ga:percentNewVisits").toString());
            pagesPerVisit = this.roundDecimal(entry.stringValueOf("ga:pageviewsPerVisit").toString());
        }

        // Make a request to the API.
        DataQuery query1 = new DataQuery(new URL("https://www.google.com/analytics/feeds/data"));
        query1.setStartDate(startDate);
        query1.setEndDate(endDate);
        query1.setDimensions("ga:pageTitle,ga:day");
        query1.setMetrics("ga:pageviews,ga:bounces,ga:visits,ga:newVisits,ga:visitors");
        query1.setMaxResults(10);
        query1.setIds(TABLE_ID);

        DataFeed dataFeed1 = analyticsService.getFeed(query1.getUrl(),
                DataFeed.class);

        // Output data to the screen.
        System.out.println("----------- Data Feed Results ----------");

        days = new ArrayList<>();
        pageViewsByDay = new ArrayList<>();
        visitsByDay = new ArrayList<>();
        newVisitsByDay = new ArrayList<>();
        for (DataEntry entry : dataFeed1.getEntries()) {
            System.out.println("\nPage Title = "
                    + entry.stringValueOf("ga:pageTitle") + "\nDay  = "
                    + entry.stringValueOf("ga:day") + "\nPageviews  = "
                    + entry.stringValueOf("ga:pageviews") + "\nga:bounces = " //page view
                    + entry.stringValueOf("ga:bounces") + "\nga:visits = "
                    + entry.stringValueOf("ga:visits") + "\nga:New Visits = " //visits
                    + entry.stringValueOf("ga:newVisits") + "\nga:visitors = " //new visits     
                    + entry.stringValueOf("ga:visitors"));

            days.add(entry.stringValueOf("ga:day").toString());
            pageViewsByDay.add(entry.stringValueOf("ga:pageviews").toString());
            visitsByDay.add(entry.stringValueOf("ga:visits").toString());
            newVisitsByDay.add(entry.stringValueOf("ga:newVisits").toString());

        }

    }

    private String roundDecimal(String number) {
        double d = new Double(number).doubleValue();
        DecimalFormat df = new DecimalFormat("#.00");
        return df.format(d).toString();
    }

    private void setAvgTimeOnSite(String time) {
        double d = new Double(time).doubleValue();
        int hours = (int) d / 3600;
        int remainder = (int) d - hours * 3600;
        int mins = remainder / 60;
        remainder = remainder - mins * 60;
        int secs = remainder;

        if (hours<10){
            avgVisitDuration_hour = String.format("%02d", hours);
        }else{
            avgVisitDuration_hour = new Integer(hours).toString();
        }
        if (mins<10){
            avgVisitDuration_min = String.format("%02d", mins);
        }else{
            avgVisitDuration_min = new Integer(mins).toString();
        }
        if (secs<10){
            avgVisitDuration_sec = String.format("%02d", secs);
        }else{
            avgVisitDuration_sec = new Integer(secs).toString();
        }
    }

    public String getTotalPageViews() {
        return totalPageViews;
    }

    public String getTotalVisits() {
        return totalVisits;
    }

    public String getTotalNewVisits() {
        return totalNewVisits;
    }

    public List<String> getPageViewsByDay() {
        return pageViewsByDay;
    }

    public List<String> getVisitsByDay() {
        return visitsByDay;
    }

    public List<String> getNewVisitsByDay() {
        return newVisitsByDay;
    }

    public List<String> getDays() {
        return days;
    }

    public String getUniqueVisitors() {
        return uniqueVisitors;
    }

    public String getAvgVisitDuration() {
        return avgVisitDuration;
    }

    public String getBounceRate() {
        return bounceRate;
    }

    public String getPercentNewVisits() {
        return percentNewVisits;
    }

    public String getPagesPerVisit() {
        return pagesPerVisit;
    }

    public String getAvgVisitDuration_hour() {
        return avgVisitDuration_hour;
    }

    public String getAvgVisitDuration_min() {
        return avgVisitDuration_min;
    }

    public String getAvgVisitDuration_sec() {
        return avgVisitDuration_sec;
    }

}
